//#define USE_CONSOLE
#include <boost/test/unit_test.hpp>
#include "Timer.hpp"
#include <iostream>
using namespace std;

static volatile int tick = 0;
static volatile int tick1 = 0;

void interrupt_function_call()
{
	++tick;
}
END_OF_FUNCTION(interrupt_function_call);

void interrupt_function_call_with_param(void * param)
{
	bool *bContinue = reinterpret_cast<bool*>(param);
	if (*bContinue)
	{
		++tick1;
	}
	else
	{
		tick1 = -1;
	}
}
END_OF_FUNCTION(interrupt_function_call_with_param);

BOOST_AUTO_TEST_CASE(ProceduralTimerRoutine)
{
	allegro_init();		// equivalent to calling int install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)()); 
	install_timer();
	LOCK_VARIABLE(tick);  
	LOCK_FUNCTION(interrupt_function_call); 
	{
		int iDelay = 1000;
		BOOST_CHECK( install_int(interrupt_function_call, iDelay)==0 );
		int iTimeToWait = 1;
		while( tick<iTimeToWait ) rest(0);	// yield
		remove_int(interrupt_function_call);
		BOOST_CHECK( tick >= iTimeToWait );
	}
	tick = 0;
	{
		int iDelay = 1000;
		BOOST_CHECK( install_int(interrupt_function_call, iDelay)==0 );
		int iTimeToWait = 1;
		while( tick<iTimeToWait ) rest(0);	// yield
		remove_int(interrupt_function_call);
		BOOST_CHECK( tick >= iTimeToWait );
	}
	tick = 0;
	{
		int iDelay = 100;
		BOOST_CHECK( install_int(interrupt_function_call, iDelay)==0 );
		int iDelay2 = 1000;
		BOOST_CHECK( install_int_ex(interrupt_function_call, iDelay2)==0 );
		int iTimeToWait = 1;
		while( tick<iTimeToWait ) rest(0);	// yield
		remove_int(interrupt_function_call);
		BOOST_CHECK( tick >= iTimeToWait );
	}
	tick1 = 0;
	{
		int iDelay = 1000;
		bool bContinue = true;
		void *void_ptr = reinterpret_cast<void*>(&bContinue);
		BOOST_CHECK( install_param_int(interrupt_function_call_with_param, void_ptr, iDelay)==0 );
		int iTimeToWait = 1;
		while( tick1<iTimeToWait ) rest(0);	// yield
		bContinue = false;
		rest(1000);	// give time to interrupt to update
		BOOST_CHECK_EQUAL( tick1, -1 );
		remove_param_int(interrupt_function_call_with_param, void_ptr);
		BOOST_CHECK( tick >= iTimeToWait );
	}
	remove_timer();
	allegro_exit();
}
BOOST_AUTO_TEST_CASE(TimerRoutine)
{
	int iSpeed = 1000;
	timer::Timer t(interrupt_function_call, iSpeed);
	LOCK_VARIABLE(tick);		// TODO: Manage variables used in interrupts cleanly
	tick = 0;
	int iTimeToWait = 5;
	t.Register();
	while( tick<iTimeToWait ) rest(0);	// yield
	t.Unregister();
}

BOOST_AUTO_TEST_CASE(Pause)
{
    system("pause");
}